import cv2
import numpy as np
import math
import DisplayOnWeb
from timeit import default_timer as timer

def cylindrical_projection(img, f):
    rows = img.shape[0]
    cols = img.shape[1]

    #f = cols / (2 * math.tan(np.pi / 8))

    blank = np.zeros_like(img)
    center_x = int(cols / 2)
    center_y = int(rows / 2)

    for y in range(rows):
        for x in range(cols):
            theta = math.atan((x - center_x) / f)
            point_x = int(f * math.tan((x - center_x) / f) + center_x)
            point_y = int((y - center_y) / math.cos(theta) + center_y)

            if point_x >= cols or point_x < 0 or point_y >= rows or point_y < 0:
                pass
            else:
                blank[y, x, :] = img[point_y, point_x, :]
    return blank

def change_size(image):
    # image=cv2.imread(read_file,1) #读取图片 image_name应该是变量
    b = cv2.threshold(image, 15, 255, cv2.THRESH_BINARY)  # 调整裁剪效果
    binary_image = b[1]  # 二值图--具有三通道
    binary_image = cv2.cvtColor(binary_image, cv2.COLOR_BGR2GRAY)
    # print(binary_image.shape)  # 改为单通道
    print('进行裁剪...')
    x = binary_image.shape[0]
    # print("高度x=",x)
    y = binary_image.shape[1]
    # print("宽度y=",y)
    edges_x = []
    edges_y = []

    for i in range(x):

        for j in range(y):

            if binary_image[i][j] == 255:
                # print("横坐标",i)
                # print("纵坐标",j)
                edges_x.append(i)
                edges_y.append(j)

    left = min(edges_x) + 50  # 左边界
    right = max(edges_x)  # 右边界
    width = right - left - 50  # 宽度

    bottom = min(edges_y)  # 底部
    top = max(edges_y)  # 顶部
    height = top - bottom  # 高度

    pre1_picture = image[left:left + width, bottom:bottom + height]  # 图片截取

    return pre1_picture  # 返回图片数据

def process_video(filename=0, func=cylindrical_projection, output='result.mp4', verbose=0,focus=2800):
    """处理视频

    :param filename: 视频源，默认为摄像头
    :param func: 处理每一帧的函数名
    :param output: 保存的文件名
    :param verbose: 可视化，0不可视化，1显示处理后的结果，2显示对比结果
    f 焦距
    """
    print("视频源：",filename)
    cap = cv2.VideoCapture(filename)  # 打开摄像头
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')  # 视频编解码器
    fps = cap.get(cv2.CAP_PROP_FPS)  # 帧数
    width, height = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 宽高
    out = cv2.VideoWriter(output, fourcc, fps, (width, height))  # 写入视频

    if verbose > 0 or filename == 0:
        print('英文下输入q停止')

    count = cap.get(cv2.CAP_PROP_FRAME_COUNT)  # 总帧数
    accum_time = 0  # 累计时间
    curr_fps = 0  # 当前帧数
    prev_time = timer()  # 上一段的时间

    while cap.isOpened():
        if count > 0:
            current = cap.get(cv2.CAP_PROP_POS_FRAMES)  # 当前第几帧
            curr_time = timer()  # 当前时间
            exec_time = curr_time - prev_time  # 处理时间
            prev_time = curr_time  # 上一段的时间设为当前时间
            accum_time = accum_time + exec_time  # 累计时间
            curr_fps = curr_fps + 1
            if accum_time >= 1:
                accum_time = accum_time - 1
                print('进度:{:.2f}%\tFPS:{}'.format(current / count * 100, curr_fps))
                curr_fps = 0  # 重置帧数
        ret, frame = cap.read()
        if ret == True:
            # h, w, s = frame.shape
            # K = np.array([[f, 0, w / 2], [0, f, h / 2], [0, 0, 1]])  # mock calibration matrix
            print('进行柱面投影...')
            result = change_size(image = func(frame,focus)) if func else frame
            result = cv2.resize(result,(1920,1080))
            # out.write(result)  # 写入帧

            result = cv2.resize(result,(800,600)) #缩小展示
            frame  = cv2.resize(frame,(800,600)) #缩小展示
            if verbose > 0 or filename == 0:
                cv2.imshow('after', result)
                if verbose == 2:
                    cv2.imshow('before', frame)
                if cv2.waitKey(1) & 0xFF == ord('q'):  # q退出
                    break
            else:
                break
    cap.release()
    out.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    process_video()
